package com.lagou.filter;

import com.lagou.po.ServiceMethodInfo;
import org.apache.dubbo.common.constants.CommonConstants;
import org.apache.dubbo.common.extension.Activate;
import org.apache.dubbo.rpc.*;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.logging.Logger;

@Activate(group = {CommonConstants.CONSUMER})
public class TpMonitorFilter implements Filter,Runnable {
   private static Logger logger=Logger.getLogger("TpMonitorFilter.class");
    Map<String, List<ServiceMethodInfo>>methodTimes=new ConcurrentHashMap<>();
    public TpMonitorFilter(){
        Executors.newSingleThreadScheduledExecutor()
                .scheduleWithFixedDelay(this,3,1, TimeUnit.SECONDS);
        Executors.newSingleThreadScheduledExecutor()
                .scheduleWithFixedDelay(new Thread(new RemoveDateThread(methodTimes)),10,30, TimeUnit.SECONDS);
    }

    @Override
    public void run() {
        System.out.println("tp90....");
        for (Map.Entry<String,List<ServiceMethodInfo>>mapEntry:methodTimes.entrySet()){
            List<ServiceMethodInfo>methodInfoList=mapEntry.getValue();
            System.out.println(mapEntry.getKey()+"方法的tp90为：");
            long time1=getTp(methodInfoList,0.9);
            System.out.println(time1);
            logger.info(mapEntry.getKey()+"方法的tp90为："+time1);

            System.out.println(mapEntry.getKey()+"方法的tp99为：");
            long time2=getTp(methodInfoList,0.99);
            System.out.println(time2);
            logger.info(mapEntry.getKey()+"方法的tp99为："+time2);

        }
    }

    @Override
    public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
        Result result = null;
        Long takeTime = 0l;
        try {
            Long startTime = System.currentTimeMillis();
            result = invoker.invoke(invocation);
            if (result.getException() instanceof Exception) {
                throw new Exception(result.getException());
            }
            takeTime=System.currentTimeMillis()-startTime;
        } catch (Exception e) {
            e.printStackTrace();
            return result;
        }
        String methodName=invocation.getMethodName();
        List<ServiceMethodInfo> methodInfoList=methodTimes.get(methodName);
        if (methodInfoList==null){
            methodInfoList=new ArrayList<>();
            methodTimes.put(methodName,methodInfoList);
        }
        methodInfoList.add(new ServiceMethodInfo(methodName,takeTime,System.currentTimeMillis()));

        return result;
    }
    private long getTp(List<ServiceMethodInfo>methodInfos,double rate){
        //计算最近一分钟的
        long endTime=System.currentTimeMillis();
        long startTime=System.currentTimeMillis()-60000;
        List<ServiceMethodInfo>requiredMethodinfos=new ArrayList<>();
        int length=methodInfos.size();
        for (int i = 0; i <length ; i++) {
            ServiceMethodInfo serviceMethodInfo=methodInfos.get(i);
            if(serviceMethodInfo.getEndTime()>=startTime&&serviceMethodInfo.getEndTime()<=endTime){
                requiredMethodinfos.add(serviceMethodInfo);
            }
        }
        //每个方法的TP90与TP99情况
        requiredMethodinfos.sort(new Comparator<ServiceMethodInfo>() {
            @Override
            public int compare(ServiceMethodInfo o1, ServiceMethodInfo o2) {
                long temp=o1.getEndTime()-o2.getEndTime();
                if (temp<0){
                    return 1;
                }else if (temp==0){
                    return 0;
                }else{
                    return -1;
                }
            }
        });
        //取出方法的TP90。。
        int index=new BigDecimal(requiredMethodinfos.size()*rate).setScale(0, BigDecimal.ROUND_HALF_UP).intValue();
        return requiredMethodinfos.get(index).getTakeTime();
    }
}
